<html xmlns="http://www.w3.org/1999/xhtml" id="states">
<head>
    <title>ステート</title>
</head>

<body>

<!-- optional -->
 
<h1>ステート</h1>

<p>この章では、一般的なステートの使用とビルトインのステートであるドラッグステートとリサイズステートについて説明をします。</p>

<!--=========================================================================-->
<!-- Major sub-heads in h2, etc                                              -->
<!--=========================================================================-->
<h2><a name="I">概要</a></h2>

<p><dfn>States</dfn>とは、通常スクリプトブロックに含まれている宣言構文や動きを使って、アプリケーション内の複合的で複雑な動きを定義するための便利なメソッドです。
 </p>
<p>ステートは、そのステートが適応されるオブジェクトの内部に書かれ、数に制限なく子を持つことができます。<tagname link="true">state</tagname>内の全てのコードは、適応される時、あたかもそのステートの親の内部に直接あるかのように書かれます。この概念はちょっと抽象的に聞こえるかもしれませんが、実際はそれがとても自然なことだということを、これからの話の中で明らかにしていきましょう。
 </p>
<h2>ステート対手続き</h2> 

<p>
宣言プログラミングは、アプリケーションの初期状態を宣言するには大変よいのですが、その後の変更は、最初に宣言された構造を非常に分かりづらくしてしまうかもしれません。Laszloの<tagname link="true">state</tagname>構文は宣言の構文を効果的な手続きにする方法を提供します。
</p>
<p>
ステートの使用の代わりとしては、プログラムの初期状態をタグを使って宣言し、それからその状態を手続きコードつまり、スクリプトで操作する、という方法があります。しかしながら、LZXの最も強力な機能のいくつかは、プログラム的な追加が難しいため、これでは問題を生じてしまいます。</p>
<p>
これは実際に、アニメーターと制約に当てはまります。制約は、Laszlo概念の全てにとっての核ですが、それらをスクリプトによって操作することは非常にトリッキーです。例えば、ここに、青い四角がマウスについてくるというちょっとしたプログラムがあります。</p>

<example title="following mouse without states">
&lt;canvas&gt;
  &lt;view bgcolor="blue" width="20" height="20"&gt;
    &lt;attribute name="x" value="${parent.getMouse('x') - 10}"/&gt;
    &lt;attribute name="y" value="${parent.getMouse('y') - 10}"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>
これは、このような種類のこと（Laszloの制約システムによって可能となること）を説明するにはよい方法ですが、プログラム上ではほとんど利点はありません。通常、オブジェクトはドラッグされた時にのみマウスについていきます。これに必要なのは、ビューがドラッグされているか否かに応じて適応されたり放されたりする宣言LZX節を記述する方法です。</p>
<p>
<tagname>state</tagname>タグはこれを可能にします。ここにあるのは、ステートを使って、上記のプログラムをマウスが押されている時にのみ青い四角がドラッグされるように書き直したものです。
</p>
<example title="using &lt;state&gt; to follow mouse">
&lt;canvas&gt;
  &lt;view bgcolor="blue" width="20" height="20"
        onmousedown="this.setAttribute('mouseIsDown', true )"
        onmouseup="  this.setAttribute('mouseIsDown', false )"&gt;
    &lt;attribute name="mouseIsDown" value="false"/&gt;
    &lt;state apply="${parent.mouseIsDown}"&gt;
      &lt;attribute name="x" value="${parent.getMouse('x') - 10}"/&gt;
      &lt;attribute name="y" value="${parent.getMouse('y') - 10}"/&gt;
    &lt;/state&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>
この強制の構文を変更したのではなく、単に<tagname>state</tagname>タグ内にあるということに注目してください。これは便利ですが、同時に多少奇妙でもあります。<tagname>state</tagname>タグは、基本的には階層の不可視節です。ステートの適応制約の中の<code>parent</code>は、ステート内部のドラッグ制約の中の<code>parent</code>と同じオブジェクトではないという事実からこのことが分かります。
</p>
<p>
この例は、ステートの抽象的な状態を強調しています。ステートはメタオブジェクトプロトコルを十分に修正（修飾）するので、そのコンテンツ（内容）は他のどこかへ格納され、適応されるのです。<span style="background-color:#FF0000">(This could conceivably be a feature of the system as a whole 
 as in, for example, <code>anLzNode.setParent(otherLzNode)</code>, but it's not). </span>
</p>
<h3>ステートの属性</h3>
<p>
ここで質問です。このように記述したら、どんなことが起きるでしょうか？
</p>
<example extract="false" title="attributes of states">
  &lt;class name="myDragState" extends="state"&gt;
    &lt;attribute name="dragMin" value="2"/&gt;
    &lt;attribute name="dragMax" value="20"/&gt;
    &lt;!-- ... --&gt;
  &lt;/class&gt;
</example>
<p>
属性<attribute>dragMin</attribute>と<attribute>dragMax</attribute>は、ステート自体に属するのでしょうか、それともステートの内容に属するのでしょうか？どちらかと言えば、前者がより強力です：これらの属性がステートそのものに属していれば、開発者はステートの特別な動作を拡張できる、つまりステートが適応するメソッドを無効にできるのです。しかしながら、後者は、最初の順序の概算、マクロのようなクラスというLZXの概念により近い形となっています。
</p>
<p>
答えは、動作は後者です。属性はステートの内容に属します。ここにそれを示す一寸したテストプログラムをお見せします。</p>

<example title="attributes pertain to container, not parent">
&lt;canvas&gt;
  &lt;class name="constrainedDragState" extends="state"&gt;
    &lt;attribute name="dragMin" value="100"/&gt;
    &lt;attribute name="dragMax" value="300"/&gt;
    &lt;attribute name="mousePos" value="${parent.getMouse( 'x' ) - 10}"/&gt;
    &lt;attribute name="x" 
               value="${Math.max(Math.min(this.dragMax, this.mousePos),
                                 this.dragMin )}"/&gt;
  &lt;/class&gt;
  
  &lt;view bgcolor="blue" width="20" height="20" x="100" y="50"
        onmousedown="myDrag.apply()"
        onmouseup="  myDrag.remove()"&gt;
    &lt;attribute name="mouseIsDown" value="false"/&gt;
    &lt;constrainedDragState name="myDrag"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<p>
<code>dragMin</code>と<code>dragMax</code>などへの参照は、全てキーワード<code>this</code>によって限定されることに注目してください。
</p>

<p>
セッターを持つステートの属性は、どのようなものであれステート自身に属しますが、そうではない属性はすべてステートの<code>apply</code>ターゲットに属します。これは意味を成します、というのも、ステートに適用される（そしてステートに保持されない）予定の属性に対するセッターはどんなものでも、applyターゲットに記述されうるからです。これがLZXでどのように動くかです。以下が、これを証明する簡単なプログラムです。
</p>

<example title="using setters in &lt;state&gt; attributes">
&lt;canvas debug="true"&gt;
  &lt;class name="testState" extends="state"&gt;
    &lt;attribute name="countApplies"  value="0"
               setter="this.countApplies = countApplies"/&gt;
    &lt;method name="apply"&gt;
      this.setAttribute('countApplies', ++this.countApplies);
      super.apply();
    &lt;/method&gt;
  &lt;/class&gt;
  &lt;button &gt;Try it
    &lt;method event="onclick"&gt;
      ts.apply();
      Debug.write("applies:" + ts.countApplies);
      ts.remove();
    &lt;/method&gt;
    &lt;testState name="ts"/&gt;
  &lt;/button&gt;
&lt;/canvas&gt;
</example>
 
<h3>パフォーマンス考慮</h3>
<p>
全てのステートはインスタンス化されています。そのため、適応されるか否かに拘らず、アプリケーションは階層の通常の節の“インスタンス化コストを支払い”ます。これは、ステートそのものが<classname>LzNode</classname>、つまり<classname>LzNode</classname>コンストラクタによって処理されなければならないものだからなのです。
</p> 
<p>
開発者がステートそのものに手を加えることができる方法を制限することの利点は、与えられたステートが制限された数の属性を持つことができ、それはランタイムによってコントロールされるということです。ステートに属性やメソッドを加えることによって、開発者が“ステート”の意味合いを変えられるようにすることは、この最適化を困難にします。</p>
 
 	
<example title="using states to animate transitions">
&lt;canvas&gt;
  &lt;window title="state demo" width="400" height="300"&gt;
    &lt;state name="max" apply="true"&gt;
      &lt;animatorgroup duration="1000" process="simultaneous"&gt;
        &lt;animator attribute="width" to="400"/&gt;
        &lt;animator attribute="height" to="300"/&gt;
        &lt;animator attribute="x" to="100"/&gt;
        &lt;animator attribute="y" to="100"/&gt;
      &lt;/animatorgroup&gt;
      &lt;text align="center" y="20%"&gt;M a x i m i z e d&lt;/text&gt;
    &lt;/state&gt;
    &lt;state name="min" &gt;
      &lt;animatorgroup duration="1000" process="simultaneous"&gt;
        &lt;animator attribute="width" to="170"/&gt;
        &lt;animator attribute="height" to="100"/&gt;
        &lt;animator attribute="x" to="0"/&gt;
        &lt;animator attribute="y" to="0"/&gt;
      &lt;/animatorgroup&gt;
      &lt;text align="center" valign="middle"&gt;Minimized&lt;/text&gt;
    &lt;/state&gt;
    &lt;button placement="title_area" align="right" height="16"&gt; Toggle
      &lt;attribute name="isMax" value="true"/&gt;
      &lt;method event="onclick"&gt;
        if (this.isMax) {parent.max.remove(); parent.min.apply();}
        else {parent.max.apply(); parent.min.remove();}
        this.isMax = !this.isMax;
      &lt;/method&gt;
    &lt;/button&gt;
&lt;/window&gt;
&lt;/canvas&gt;
</example>
<p>
ステート要素は、属性<attribute>apply</attribute>、<attribute>onapply</attribute>、<attribute>onremove</attribute>、そして<tagname>view</tagname>とともに宣言されます。<attribute>apply</attribute>、<attribute>onapply</attribute>、<attribute>onremove</attribute>はステートそのものの動作をコントロールします。それ以外の属性や子は、ステートが適応された時に、ステートの親に対して適応されます。
</p>
<h3>ビューの子ではないステート</h3>
<p>
もし、ステートが、<tagname>layout</tagname>や<tagname>animator</tagname>といったビューではない要素の子である場合、ビューの属性は意味を成しません。これら他の要素のうちの1つに適応される属性を、<tagname link="true">attribute</tagname>要素を使ってステートに加えることは可能です。
</p>
 


<h3><a name="II">ステートはビューあるいはクラスを含む</a></h3>


<p>
ステートは、そのステートが適応された時にだけ生成されるビューやクラスを持つこともできます。
</p>

<pre>
&lt;state name="showchildren"&gt;
  &lt;view y="13" x="13" name="children"&gt;
    &lt;simplelayout/&gt;
    &lt;treeitem grown="${classroot.opened}"&gt;
      &lt;datapath xpath="*" pooling="true"/&gt;
    &lt;/treeitem&gt;
   &lt;/view&gt;
&lt;/state&gt;
</pre>

<h3>ドラッグステート</h3>
<p>
どんな目的にも合うように、<tagname>state</tagname> をサブクラス化することができます。LZXは、一般的な問題を解決するために、2つのそういった<tagname>state</tagname>のサブクラスを持っています。
</p>
<p>
この例では、異なるビューに適応できるステートを機能的に生成するために<tagname>dragstate</tagname>クラスをサブクラス化する方法を紹介します。
</p>

<example title="Dropshadow done using states">
&lt;canvas height="200"&gt;
  &lt;class extends="dragstate" name="fadeDragger" pooling="true"&gt;
    &lt;method event="onapply"&gt;
      parent.bringToFront();
      parent.setAttribute('opacity', .5)
    &lt;/method&gt;
    &lt;method event="onremove"&gt;
      parent.setAttribute('opacity', 1)
    &lt;/method&gt;
    &lt;view name="hShadow" x="10" y="${parent.body.height}"
          width="${parent.body.width}" height="10"
          opacity=".2" bgcolor="black"/&gt;
    &lt;view name="vShadow"  x="${parent.body.width}" y="10"
          width="10" height="${parent.body.height - 10}"
          opacity=".2" bgcolor="black"/&gt;
  &lt;/class&gt;
  
  &lt;view
        onmousedown="myFadeDragger.apply()"
        onmouseup="myFadeDragger.remove()"&gt;
    &lt;fadeDragger name="myFadeDragger"/&gt;
    &lt;view name="body" width="40" height="40" bgcolor="blue"/&gt;
  &lt;/view&gt;
  &lt;view x="100" y="100"
        onmousedown="myFadeDragger.apply()"
        onmouseup="myFadeDragger.remove()"&gt;
    &lt;fadeDragger name="myFadeDragger"/&gt;
    &lt;view name="body" width="60" height="60" bgcolor="red"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<!-- See other chapters in the D3 guide and also the wiki for more informtion on formatting chapters --> 
<!-- Here is a list of some topics you may want to discuss in this chapter-->


 
<?ignore 

<h3>Resizestate</h3>




 
 States and Performance  
 
 

It would be good to point out the use of a multi-frame resource for different states (like what's done in window and button)
 

    Avoid changing a state's view at runtime
     Costly
 
  Use "frames" instead
 States
    Analogous to layouts: temporal placement of multiple views
       two uses/benefits
           Express changes that can be applied at runtime
           To optimize application performance 
 Views aren't created until needed
       A description of an instance hierarchy 
       can be applied or removed at runtime
       Applying state with a constraint
           Adds constraint, doesn't replace
Tags discussed in this chapter: state, dragstate, resizestate,
 ?>

</body>
</html>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.              *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
